/*
 * Copyright (c) 2012 Universidad Antonio de Nebrija.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Apache License v2.0
 * which accompanies this distribution, and is available at
 * http://www.apache.org/licenses/LICENSE-2.0.html
 * 
 * Contributors:
 *    Universidad Antonio de Nebrija - initial API, implementation and documentation
 */
package com.nebrija.riif.model;

/**
 * Class that represents the environment token
 * Needs to be completed once the grammar is fixed
 * @author asanchep
 */
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;

public class Environment implements RIIFElement, RIIFPropertiesContainer{
	protected String name = "";

	/** input and output parameters */
	private HashMap<String,Parameter> parameters = new HashMap<String,Parameter>();
	/** Namespace for all the constants included in this component*/
	private HashMap<String, Constant> constants = new HashMap<String, Constant>();
	
	public Environment(){
	}
	
	public Environment(String name){
		this.name=name;
	}
	
	/**
	 * Add a parameter as an element of this environment
	 * @param par the parameter to be added
	 * @return an error string or an empty string if no error was found
	 */
	public String addParameter(Parameter par){
		if (par==null){
			return "Null";
		}
		if (par.getName()==null || par.getName().equals("")){
			return "Null";
		}
		if (parameters.get(par.getName())!=null){
			return "An element with that name already exists in this component"; // TODO Internationalization
		}
		parameters.put(par.getName(), par);
		return "";
	}
	
	@Override
	public void resolve(RIIFElement container) {
		for (Parameter element: parameters.values()){
			element.resolve(this);
		}
		
	}	
	
	@Override
	public void clear(RIIFElement container) {
		for (Parameter element: parameters.values()){
			element.clear(this);
		}
		
	}

	@Override
	public String getName() {
		return name;
	}	
	
	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder(getName());
		
		
		sb.append("\n->PARAMETERS: \n");
		Set<String> paramNames = parameters.keySet();
		for(String name: paramNames){
			sb.append("\t").append(parameters.get(name).toString());
		}
		
		sb.append("\n->CONSTANTS: \n");
		Set<String> constantNames = constants.keySet();
		for(String name: constantNames){
			sb.append("\t").append(constants.get(name).toString());
		}
		
		return sb.toString();
	}
	
	/**
	 * Function that adds a constant to this environment. It is added to the constant list
	 * @param co the constant to be added
	 * @return an error string or an empty string if no error
	 */
	public String addConstant(Constant co) {
		if (co==null){
			return "Null";
		}
		if (co.getName()==null || co.getName().equals("")){
			return "Null";
		}
		if (hasConstant(co)){
			return "A constant with that name already exists in this component"; // TODO Internationalization
		}
		constants.put(co.getName(), co);
		return "";
	}
	
	/**
	 * Check if a constant exists
	 * @param co constant
	 * @return true if it exists, false otherwise
	 */	
	public boolean hasConstant(Constant co) {
		if (constants.get(co.getName())!=null){
			return true;
		}
		return false;
	}	
	
	public RIIFElement getElement (String name){
		RIIFElement element = constants.get(name);
		if(element == null){
			element = parameters.get(name);
		}
		return element;
	}

	@Override
	public RIIFProperties getPropertiesElement(String name) {
		RIIFProperties props = constants.get(name);
		if(props == null){
			props = parameters.get(name);
		}
		return props;
	}

	@Override
	public int getChildCount() {
		// TODO Auto-generated method stub
		return constants.size()+parameters.size();
	}

	@Override
	public Set<String> getElementNames() {
		Set<String> elementNames = new HashSet<String>();
		elementNames.addAll(constants.keySet());
		elementNames.addAll(parameters.keySet());
		return elementNames;
	}
}
